#include <iostream>
#include <fstream>
#include <vector>
#include <jsoncpp/json/json.h>
#include "Function.h"
#include "Spline.h"
#include "CurveFitting.h"

using namespace std;

class fun_heart1 : public Function {
public:
    double operator()(const double& x) const { 
        return 2.0 / 3.0 * (sqrt(fabs(x)) + sqrt(3 - x * x)); 
    }
}f1;

class fun_heart2 : public Function {
public:
    double operator()(const double& x) const { 
        return 2.0 / 3.0 * (sqrt(fabs(x)) - sqrt(3 - x * x)); 
    }
}f2;

int main() {
    
    ifstream ifs("./input/E_input.json");
    ofstream ofs;
    ofs.open("./output/E_output.txt");

    Json::Reader reader;
    Json::Value obj;
    reader.parse(ifs, obj);
    
    //读取条件
    vector<int> KnotsNum;
    for (int i = 0; i < obj["E_KnotsNum"].size(); i++) {
        KnotsNum.push_back(obj["E_KnotsNum"][i].asInt());
    }

    ofs << "ppspline fitting heart function: " << endl;
    for (int i = 0; i < KnotsNum.size(); i++) {
        int N = KnotsNum[i];
        ofs << "When N = " << N << " : " << endl;
        
        //插值点选取
        int num1 = floor((N - 4.0) / 4.0);
        int num2 = floor((N - 4.0) / 2.0) - num1;
        vector<vector<double>> knots;
        knots.push_back(vector<double>{ 0, 2.0 * sqrt(3) / 3.0 });
        for (int j = 0; j < num1; j++) {
            double x = sqrt(3) / (num1 + 1) * (j + 1);
            knots.push_back(vector<double>{ x, f1(x) });
        }
        knots.push_back(vector<double>{ sqrt(3), f1(sqrt(3)) });
        for (int j = 0; j < num2; j++) {
            double x = sqrt(3) - sqrt(3) / (num2 + 1) * (j + 1);
            knots.push_back(vector<double>{ x, f2(x) });
        }
        knots.push_back(vector<double>{ 0, -2.0 * sqrt(3) / 3.0 });
        for (int j = 0; j < num2; j++) {
            double x = -sqrt(3) / (num2 + 1) * (j + 1);
            knots.push_back(vector<double>{ x, f2(x) });
        }
        knots.push_back(vector<double>{ -sqrt(3), f1(-sqrt(3)) });
        for (int j = 0; j < num1; j++) {
            double x = -sqrt(3) + sqrt(3) / (num1 + 1) * (j + 1);
            knots.push_back(vector<double>{ x, f1(x) });
        }
        knots.push_back(vector<double>{ 0, 2.0 * sqrt(3) / 3.0 });

        //插值拟合
        CurveFitting<3, ppform> ppspline_fit(knots);
        vector<vector<double>> pp_curve = ppspline_fit.get_curve();
        for (int j = 0; j < pp_curve.size(); j++) {
            //输出每一维的插值结果
            for (int k = 0; k < pp_curve[j].size(); k++) {
                ofs << pp_curve[j][k] << " ";
            }
            ofs << endl;
        }
        ofs << endl;
    }

    ofs.close();

    return 0;
}
